package se.webbzon.boltzmann.editor.component.sequence;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.Collection;

import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

import se.webbzon.boltzmann.editor.component.AbstractComponent;
import se.webbzon.boltzmann.editor.component.sequence.panel.AbstractRowPanel;
import se.webbzon.boltzmann.editor.component.sequence.panel.factory.AbstractRowPanelFactory;
import se.webbzon.boltzmann.editor.component.sequence.panel.factory.AbstractRowPanelFactoryGroup;
import se.webbzon.boltzmann.game.sequence.builder.AbstractSequenceRow;

public class GenericRowPanel extends AbstractComponent {
	
	// Auto generated serial version UID
	private static final long serialVersionUID = -8987175232987194658L;

	// A collection of all listener to this panel
	private final Collection<GenericRowListener> listeners;
	
	// The buttons of this panel
	private final JButton applyButton;

	// The row panel factory group associated with this panel
	private final AbstractRowPanelFactoryGroup factoryGroup;
	
	// The currently selected row
	private AbstractSequenceRow row;
	
	// The currently selected row panel
	private AbstractRowPanel panel;
	
	/*============================================================
	Constructors
	============================================================*/
	
	public GenericRowPanel(AbstractRowPanelFactoryGroup factoryGroup) {
		super("Generic Row Panel");
		this.factoryGroup = factoryGroup;
		listeners = new ArrayList<GenericRowListener>();
		setLayout(new BorderLayout());
		setBorder(BorderFactory.createTitledBorder("Misc:"));
		
		panel = new EmptyRowPanel();
		add(panel,BorderLayout.CENTER);
		
		JPanel buttonPanel = new JPanel();
		buttonPanel.setLayout(new BorderLayout());
		applyButton = new JButton(new ApplyAction());
		buttonPanel.add(applyButton,BorderLayout.WEST);
		add(buttonPanel,BorderLayout.SOUTH);
		
		editRow(null);
	}
	
	/*============================================================
	Public Methods
	============================================================*/
	
	/** Adds a listener to this generic row panel. **/
	public boolean addListener(GenericRowListener listener) {
		return listeners.add(listener);
	}
	
	/** Removes a listener from this generic row panel. **/
	public boolean removeListener(GenericRowListener listener) {
		return listeners.remove(listener);
	}
	
	/** Clears all the listeners in this generic row panel. **/
	public void clearListener() {
		listeners.clear();
	}
	
	/** Returns the currently selected sequence row. **/
	public AbstractSequenceRow getSelectedRow() {
		return row;
	}
	
	/** Starts the editing of the given sequence row. **/
	public void editRow(AbstractSequenceRow row) {
		if (this.row != row) {
			this.row = row;
			
			// Notify edit
			for (GenericRowListener listener : listeners.toArray(new GenericRowListener[0]))
				listener.editRow(GenericRowPanel.this, row);
			
			remove(panel);
			if (row == null) {
				
				panel = new EmptyRowPanel();
				
				// Disable the apply button
				applyButton.setEnabled(false);
				
			} else {
				// Retrieve the panel factory
				AbstractRowPanelFactory factory = 
						factoryGroup.getFactory(row.getName());
				if (factory == null) {
					panel = new EmptyRowPanel();
					applyButton.setEnabled(false);
				} else {
					panel = factory.makeNew(row);
					applyButton.setEnabled(true);
				}
			}
			
			// Add the generic panel to this panel
			add(panel,BorderLayout.CENTER);
		}
	}
	
	/*============================================================
	Private Classes
	============================================================*/
	
	private final class EmptyRowPanel extends AbstractRowPanel {
		
		// Auto generated serial version UID
		private static final long serialVersionUID = -5919827581466455173L;
		
		/*============================================================
		Constructor
		============================================================*/

		public EmptyRowPanel() {
			super(null);
			add(new JLabel("Nothing"));
		}
		
		/*============================================================
		Public Methods
		============================================================*/
		
		@Override public boolean apply(Collection<String> errorMessages) {
			return true;
		}
		
	}
	
	/** An abstract action used for the apply button. **/
	private final class ApplyAction extends AbstractAction {
		
		// Auto generated serial version UID
		private static final long serialVersionUID = 4512031088140520225L;
		
		/*============================================================
		Constructor
		============================================================*/

		public ApplyAction() {
			putValue(AbstractAction.NAME,"Apply");
		}

		/*============================================================
		Public Methods
		============================================================*/
		
		@Override public void actionPerformed(ActionEvent event) {
			if (row != null) {
				ArrayList<String> errorMessages = new ArrayList<String>();
				if (!panel.apply(errorMessages)) {
					if (errorMessages.size() > 0) {
						String message = errorMessages.get(0);
						JOptionPane.showMessageDialog(	panel, message, 
														"Error", 
														JOptionPane.ERROR_MESSAGE);
					}
				} else {
					// Notify change
					for (GenericRowListener listener : listeners.toArray(new GenericRowListener[0]))
						listener.changeRow(GenericRowPanel.this, row);
				}
			}
		}
		
	}

}
